#include "Util.hpp"

#include <iostream>
#include <iomanip>
#include <ctime>
#include <string>
#include <sstream>
#include <chrono>
#include <regex>

#ifdef _WIN32
#include <Windows.h>
#else
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#endif

//#pragma warning(disable : 4996)

namespace cybertron {
	int64_t Util::time_now()
	{
		return int64_t(time(nullptr));
	}

	int64_t Util::time_now_ms() {
		auto now = std::chrono::system_clock::now();
		return std::chrono::time_point_cast<std::chrono::milliseconds>(now).time_since_epoch().count();
	}

	int Util::get_current_pid()
	{
#ifdef _WIN32
		return GetCurrentProcessId();
#else
		return ::getpid();
#endif
	}
	bool Util::valid_dir(const std::string & dir)
	{
		struct stat s;
		int ret = stat(dir.c_str(), &s);
		if (ret != 0)
			return false;

		if (s.st_mode & S_IFDIR) {
			return true;
		}
		else {
			return false;
		}
	}
	std::string Util::format_datetime_ms(int64_t time_ms)
	{
		time_ms += 8 * 3600 * 1000;  //convert UTC to UTC+8

		struct tm buf;
		int64_t time_sec = time_ms / 1000;
#ifdef _WIN32
		gmtime_s(&buf, &time_sec);
#else
		gmtime_r(&time_sec, &buf);
#endif
		std::stringstream transTime;
		transTime << std::put_time(&buf, "%Y-%m-%d %H:%M:%S");
		transTime << "." << std::setfill('0') << std::setw(3) << time_ms % 1000;
		return transTime.str();
	}
	std::string Util::format_datetime(int64_t time_sec)
	{
		time_sec += 8 * 3600;  //convert UTC to UTC+8

		struct tm buf;
#ifdef _WIN32
		gmtime_s(&buf, &time_sec);
#else
		gmtime_r(&time_sec, &buf);
#endif
		std::stringstream transTime;
		transTime << std::put_time(&buf, "%Y-%m-%d %H:%M:%S");
		return transTime.str();
	}
//
//	int64_t Util::parse_datetime(const std::string & str)
//	{
//		std::tm tm = {};
//		std::stringstream ss(str);
//		ss >> std::get_time(&tm, "%Y-%m-%d %H:%M:%S");
//		auto tp = std::chrono::system_clock::from_time_t(std::mktime(&tm));
//		return std::chrono::duration_cast<std::chrono::seconds>(tp.time_since_epoch()).count();
//	}

	std::string Util::replace(const std::string &in, const std::string &from, const std::string &to)
	{
		return std::regex_replace(in, std::regex(from), to);
	}
}